package com.snow.useviewdemo.util.fix;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

import kotlin.TypeCastException;
import kotlin.jvm.internal.Intrinsics;

/**
 * Created by zhaoyingtao
 * Date: 2020/12/14
 * Describe:修复ActivityRecord not found问题
 * 使用，在application中调用 IActivityManagerHooks.iActivityManagerHook();
 */
public class IActivityManagerHooks {
    private static final String TAG = "IActivityManagerHook";

    @SuppressLint({"PrivateApi"})
    public static void iActivityManagerHook() {
        Log.w("IActivityManagerHook", "========Build.VERSION.SDK_INT============" + Build.VERSION.SDK_INT);
        if (Build.VERSION.SDK_INT >= 24 && Build.VERSION.SDK_INT <= 28) {//7.0到9.0
            try {
                Class singletonCls = Class.forName("android.util.Singleton");
                Object iActivityManagerSingleton = Build.VERSION.SDK_INT <= 25 ? getIActivityManagerSingletonInstanceN(singletonCls) : getIActivityManagerSingletonInstance(singletonCls);
                if (iActivityManagerSingleton == null || singletonCls == null) {
                    return;
                }
                Field instanceField = singletonCls.getDeclaredField("mInstance");
                if (instanceField == null) {
                    return;
                }
                instanceField.setAccessible(true);
                Object iActivityManager = instanceField.get(iActivityManagerSingleton);
                if (iActivityManager == null) {
                    Log.w("IActivityManagerHook", "Not found IActivityManager instance.");
                    return;
                }
                IActivityManagerProxy proxy = new IActivityManagerProxy(iActivityManager);
                Class iActivityManagerCls = Class.forName("android.app.IActivityManager");
                if (iActivityManagerCls == null) {
                    return;
                }
                Object iActivityManageProxy = Proxy.newProxyInstance(iActivityManagerCls.getClassLoader(), new Class[]{iActivityManagerCls}, proxy);
                instanceField.set(iActivityManagerSingleton, iActivityManageProxy);
                Log.w("IActivityManagerHook", "IActivityManager hook success.");
            } catch (Exception e) {
                Log.w("IActivityManagerHook", "IActivityManager hook fail: ");
            }
        }
    }

    @SuppressLint({"PrivateApi"})
    private static Object getIActivityManagerSingletonInstanceN(Class singletonCls) throws ClassNotFoundException, IllegalAccessException {
        Class activityManagerNativeCls = Class.forName("android.app.ActivityManagerNative");
        Object iActivityManagerSingleton = null;
        Field[] var6 = activityManagerNativeCls.getDeclaredFields();
        int var7 = var6.length;
        for (int var5 = 0; var5 < var7; ++var5) {
            Field field = var6[var5];
            Intrinsics.checkExpressionValueIsNotNull(field, "field");
            if (Intrinsics.areEqual(field.getType(), singletonCls)) {
                field.setAccessible(true);
                iActivityManagerSingleton = field.get((Object) null);
                break;
            }
        }
        if (iActivityManagerSingleton == null) {
            Log.w("IActivityManagerHook", "Not found IActivityManager singleton field in class ActivityManagerNative.");
        }
        return iActivityManagerSingleton;
    }

    private static Object getIActivityManagerSingletonInstance(Class singletonCls) throws IllegalAccessException {
        Object iActivityManagerSingleton = null;
        Field[] var5 = ActivityManager.class.getDeclaredFields();
        int var6 = var5.length;

        for (int var4 = 0; var4 < var6; ++var4) {
            Field field = var5[var4];
            Intrinsics.checkExpressionValueIsNotNull(field, "field");
            if (Intrinsics.areEqual(field.getType(), singletonCls)) {
                field.setAccessible(true);
                iActivityManagerSingleton = field.get((Object) null);
                break;
            }
        }
        if (iActivityManagerSingleton == null) {
            Log.w("IActivityManagerHook", "Not found IActivityManager singleton field in class ActivityManager.");
        }
        return iActivityManagerSingleton;
    }

    private static class IActivityManagerProxy implements InvocationHandler {
        Object iActivityManager;

        public IActivityManagerProxy(Object iActivityManager) {
            this.iActivityManager = iActivityManager;
        }

        @Nullable
        public Object invoke(@Nullable Object proxy, @NotNull Method method, @Nullable Object[] args) throws InvocationTargetException, IllegalAccessException {
            if (TextUtils.equals(method.getName(), "isTopOfTask")) {
                Object o = null;
                try {
                    o = method.invoke(iActivityManager, args);
                    Log.w(TAG, "isTopOfTask() invoke success");
                } catch (Exception e) {
                    Log.w(TAG, "isTopOfTask() invoke exception: $e");
                }
                return o;
            }
            return method.invoke(iActivityManager, args);
        }
    }
}